#include "PickHandler.h"
#include "NodeData.h"
#include "SceneManagerModel.h"
#include <QtGUI/QItemSelectionModel>

bool PickHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
{
    osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
    if (!viewer) return false;

    switch(ea.getEventType())
    {
        case(osgGA::GUIEventAdapter::PUSH):
		{
            _mx = ea.getX();
            _my = ea.getY();
            pick(ea,viewer);
		}
        break;

        case(osgGA::GUIEventAdapter::MOVE):
        {
            _mx = ea.getX();
            _my = ea.getY();
        }
        break;

        default:
           break;
    }
    return false;
}


bool PickHandler::pick(const osgGA::GUIEventAdapter &ea, osgViewer::Viewer *viewer)
{
    osg::Node* scene = viewer->getSceneData();
    if (!scene) return false;

    // use non dimensional coordinates - in projection/clip space
    osgUtil::LineSegmentIntersector* picker = new osgUtil::LineSegmentIntersector( osgUtil::Intersector::PROJECTION, ea.getXnormalized(),ea.getYnormalized() );
    osgUtil::IntersectionVisitor iv(picker);
    viewer->getCamera()->accept(iv);

    if (!picker->containsIntersections())
    {
		return false;
	}
	
	osgUtil::LineSegmentIntersector::Intersection intersection = picker->getFirstIntersection();
    osg::NodePath& nodePath = intersection.nodePath;
	osg::Node* node = findSelectableNode(nodePath);
	if(!node)
	{
		return false;
	}

	osg::notify(osg::NOTICE) << "Picked: " << node->getName() << std::endl;
	const SceneManagerModel* model = dynamic_cast<const SceneManagerModel*>(_selectionModel->model());
	if(!model)
	{
		return false;
	}

	if(_selectionManager->isSelected(node))
	{
		_selectionModel->select(model->index(node), QItemSelectionModel::Deselect);
	}
	else
	{
		_selectionModel->select(model->index(node), QItemSelectionModel::Select);
	}

    ea.setHandled(true);
	return true;
}


osg::Node* PickHandler::findSelectableNode(const osg::NodePath& nodePath)
{
	if(nodePath.size() == 0)
	{
		return NULL;
	}

	int i = nodePath.size() - 1;
	osg::Node* node = nodePath[i--];
	while(i >= 0 && node && isSelectable(node) == false)
	{
		node = nodePath[i--];
	}
	
	if(i < 0)
	{
		return NULL;
	}

	return node;
}


bool PickHandler::isSelectable(osg::Node *pNode)
{
	const NodeData* pNodeData = dynamic_cast<NodeData*>( pNode->getUserData() );
	return pNodeData ? pNodeData->selectable : false;
}
